package customerEnter.Frame.javassist;

import static com.google.common.collect.Maps.newHashMap;

import java.util.List;
import java.util.Map;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import javassist.util.HotSwapper;
import customerEnter.Frame.DaoDataTransmission.WebAppsInfo;
import customerEnter.Frame.bean.BeansMethodsInfo;
import customerEnter.Frame.bean.BeansParametersInfo;
import customerEnter.tool.WhetherToEmpty;

/**
 * 
 * 类描述：
 * 
 * 类名称：FrameJavassistUtils
 * 
 * 创建人：dy
 * 
 * 创建时间：2017-9-18 上午9:48:07
 * 
 */
public class FrameJavassistUtils {
	/**
	 * 設置參數
	 * 
	 * @throws NotFoundException
	 */
	static Map<String, BeansMethodsInfo>	classNameMethods	= newHashMap();

	// 設置各個類的方法 和參數
	private static void setClassNameAndMethodParameter(String ClassName, String methodName) throws Exception {
		if (classNameMethods.containsKey(ClassName)) {
			BeansMethodsInfo beansMethodsInfo = classNameMethods.get(ClassName);
			Map<String, BeansParametersInfo> map = beansMethodsInfo.getClassMethods();
			if (!map.containsKey(methodName)) {
				BeansParametersInfo beansParametersInfo = new BeansParametersInfo();
				SetAttributeName(ClassName, methodName, beansParametersInfo, beansMethodsInfo);
				map.put(methodName, beansParametersInfo);
			}
		} else {
			BeansMethodsInfo beansMethodsInfo = new BeansMethodsInfo();
			Map<String, BeansParametersInfo> map = newHashMap();
			// 設置類名字和方法名字
			//
			BeansParametersInfo beansParametersInfo = new BeansParametersInfo();
			SetAttributeName(ClassName, methodName, beansParametersInfo, beansMethodsInfo);
			map.put(methodName, beansParametersInfo);
			beansMethodsInfo.setClassMethods(map);
			classNameMethods.put(ClassName, beansMethodsInfo);
		}
	}

	private static void SetAttributeName(String className, String methodName, BeansParametersInfo beansParametersInfo,
			BeansMethodsInfo beansMethodsInfo) throws Exception {
		ClassPool cp = ClassPool.getDefault();

		String path = WebAppsInfo.webUrl;
		if (!WhetherToEmpty.StringWhetherToEmpty(path)) {
			cp.appendClassPath(path + "WEB-INF/classes");
		}
		CtClass cc = cp.get(className);// 獲取類
		if (cc.isFrozen()) {
			cc.defrost();// 解凍
		}
		CtMethod m = cc.getDeclaredMethod(methodName);// 獲取類運行的方法
		MethodInfo methodInfo = m.getMethodInfo();// 獲取方法的信息
		beansMethodsInfo.setClass1(cc);// 設置類
		CodeAttribute codeAttribute = methodInfo.getCodeAttribute();// 獲取參數的信息
		LocalVariableAttribute attribute = (LocalVariableAttribute) codeAttribute
				.getAttribute(LocalVariableAttribute.tag);// 轉換類型
		beansParametersInfo.setCtMethod(m);

		Map<String, Integer> map = newHashMap();
		Map<Integer, CtClass> typeMap = newHashMap();
		int size = m.getParameterTypes().length;// 獲取參數的個數
		CtClass[] classes = m.getParameterTypes();
		for (int i = 1; i <= classes.length; i++) {
			typeMap.put(i, classes[i - 1]);
		}
		for (int i = 1; i <= size; i++) {
			map.put(attribute.variableName(i), i);// 放入
		}
		beansParametersInfo.setMap(map);
		beansParametersInfo.setTypeClass(typeMap);
	}

	public static void writeClassParamet(String ClassName, String methodName, List<String> paratemsNames,
			Map<String, String[]> values) throws Exception {
		setClassNameAndMethodParameter(ClassName, methodName);
		BeansMethodsInfo beansMethodsInfo = classNameMethods.get(ClassName);
		CtClass cc = beansMethodsInfo.getClass1();
		BeansParametersInfo beansParametersInfo = beansMethodsInfo.getClassMethods().get(methodName);
		CtMethod m = beansParametersInfo.getCtMethod();
		String tens = "";
		for (String string : paratemsNames) {
			int weiz = beansParametersInfo.getMapValues(string);
			CtClass ctClass = beansParametersInfo.getMapTypeValues(weiz);
			String str[] = values.get(string);
			if ("String".equals(ctClass.getSimpleName())) {
				for (String string2 : str) {
					tens += " $" + weiz + "=\"" + string2 + " \"; ";
				}
			} else {
				for (String string2 : str) {
					tens += " $" + weiz + "=" + string2 + "; ";
				}
			}
		}
		// cc.setSuperclass(cc);
		m.insertBefore("{   " + tens + "  }");
		cc.writeFile(); // 更新class文件 會凍結
		cc.defrost();// 解凍
		//HotSwapper swap = new HotSwapper(8230);
		//swap.reload(ClassName, cc.toBytecode());
		cc.detach();
	}
}
